/*
 * Copyright (C) 2005 - 2013 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008 - 2013 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2010 - 2013 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef ARKCORECORE_CHAT_H
#define ARKCORECORE_CHAT_H

#include "SharedDefines.h"
#include "Player.h"

#include <vector>

class ChatHandler;
class WorldSession;
class WorldObject;
class Creature;
class Player;
class Unit;
struct GameTele;

class ChatCommand
{
public:
    const char * Name;
    uint32 SecurityLevel;          // function pointer required correct align (use uint32)
    bool AllowConsole;
    bool (*Handler) (ChatHandler*, const char* args);
    std::string Help;
    ChatCommand * ChildCommands;
};

class ChatHandler
{
public:
    WorldSession * GetSession ()
    {
        return m_session;
    }
    explicit ChatHandler (WorldSession* session) :
            m_session(session)
    {
    }
    explicit ChatHandler (Player* player) :
            m_session(player->GetSession())
    {
    }
    ~ChatHandler ()
    {
    }

    static void FillMessageData (WorldPacket *data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit *speaker);

    void FillMessageData (WorldPacket *data, uint8 type, uint32 language, uint64 target_guid, const char* message)
    {
        FillMessageData(data, m_session, type, language, NULL, target_guid, message, NULL);
    }

    void FillSystemMessageData (WorldPacket *data, const char* message)
    {
        FillMessageData(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, 0, message);
    }

    static char* LineFromMessage (char*& pos)
    {
        char* start = strtok(pos, "\n");
        pos = NULL;
        return start;
    }

    // function with different implementation for chat/console
    virtual const char *GetArkCoreString (int32 entry) const;
    virtual void SendSysMessage (const char *str);

    void SendSysMessage (int32 entry);
    void PSendSysMessage (const char *format, ...) ATTR_PRINTF(2, 3);
    void PSendSysMessage (int32 entry, ...);
    std::string PGetParseString (int32 entry, ...);

    int ParseCommands (const char* text);

    static ChatCommand* getCommandTable ();

    bool isValidChatMessage (const char* msg);
    void SendGlobalSysMessage (const char *str);

    bool hasStringAbbr (const char* name, const char* part);

    // function with different implementation for chat/console
    virtual bool isAvailable (ChatCommand const& cmd) const;
    virtual std::string GetNameLink () const
    {
        return GetNameLink(m_session->GetPlayer());
    }
    virtual bool needReportToTarget (Player* chr) const;
    virtual LocaleConstant GetSessionDbcLocale () const;
    virtual int GetSessionDbLocaleIndex () const;

    bool HasLowerSecurity (Player* target, uint64 guid, bool strong = false);
    bool HasLowerSecurityAccount (WorldSession* target, uint32 account, bool strong = false);

    void SendGlobalGMSysMessage (const char *str);
    Player* getSelectedPlayer ();
    Creature* getSelectedCreature ();
    Unit* getSelectedUnit ();
    WorldObject* getSelectedObject ();

    char* extractKeyFromLink (char* text, char const* linkType, char** something1 = NULL);
    char* extractKeyFromLink (char* text, char const* const * linkTypes, int* found_idx, char** something1 = NULL);

    // if args have single value then it return in arg2 and arg1 == NULL
    void extractOptFirstArg (char* args, char** arg1, char** arg2);
    char* extractQuotedArg (char* args);

    uint32 extractSpellIdFromLink (char* text);
    uint64 extractGuidFromLink (char* text);
    GameTele const* extractGameTeleFromLink (char* text);
    bool GetPlayerGroupAndGUIDByName (const char* cname, Player* &plr, Group* &group, uint64 &guid, bool offline = false);
    std::string extractPlayerNameFromLink (char* text);
    // select by arg (name/link) or in-game selection online/offline player
    bool extractPlayerTarget (char* args, Player** player, uint64* player_guid = NULL, std::string* player_name = NULL);

    std::string playerLink (std::string const& name) const
    {
        return m_session ? "|cffffffff|Hplayer:" + name + "|h[" + name + "]|h|r" : name;
    }
    std::string GetNameLink (Player* chr) const
    {
        return playerLink(chr->GetName());
    }

    GameObject* GetNearbyGameObject ();
    GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid (uint32 lowguid, uint32 entry);
    bool HasSentErrorMessage ()
    {
        return sentErrorMessage;
    }
    void SetSentErrorMessage (bool val)
    {
        sentErrorMessage = val;
    }
    ;
    static bool LoadCommandTable ()
    {
        return load_command_table;
    }
    static void SetLoadCommandTable (bool val)
    {
        load_command_table = val;
    }
    ;

protected:
    explicit ChatHandler () :
            m_session(NULL)
    {
    }          // for CLI subclass
    static bool SetDataForCommandInTable (ChatCommand *table, const char* text, uint32 security, std::string const& help, std::string const& fullcommand);
    bool ExecuteCommandInTable (ChatCommand *table, const char* text, const std::string& fullcmd);
    bool ShowHelpForCommand (ChatCommand *table, const char* cmd);
    bool ShowHelpForSubCommands (ChatCommand *table, char const* cmd, char const* subcmd);

    bool HandleAHBotOptionsCommand (const char * args);
    bool HandleNameAnnounceCommand (const char* args);
    bool HandleGMNameAnnounceCommand (const char* args);
    bool HandleGMAnnounceCommand (const char* args);
    bool HandleGMNotifyCommand (const char* args);

    bool HandleBanAccountCommand (const char* args);
    bool HandleBanAccountByCharCommand (const char* args);
    bool HandleBanCharacterCommand (const char* args);
    bool HandleBanIPCommand (const char* args);
    bool HandleBanInfoAccountCommand (const char* args);
    bool HandleBanInfoCharacterCommand (const char* args);
    bool HandleBanInfoIPCommand (const char* args);
    bool HandleBanListAccountCommand (const char* args);
    bool HandleBanListCharacterCommand (const char* args);
    bool HandleBanListIPCommand (const char* args);

    bool HandleCastCommand (const char *args);
    bool HandleCastBackCommand (const char *args);
    bool HandleCastDistCommand (const char *args);
    bool HandleCastSelfCommand (const char *args);
    bool HandleCastTargetCommand (const char *args);

    bool HandleCharacterCustomizeCommand (const char * args);
    bool HandleCharacterChangeFactionCommand (const char * args);
    bool HandleCharacterChangeRaceCommand (const char * args);
    bool HandleCharacterDeletedDeleteCommand (const char* args);
    bool HandleCharacterDeletedListCommand (const char* args);
    bool HandleCharacterDeletedRestoreCommand (const char* args);
    bool HandleCharacterDeletedOldCommand (const char* args);
    bool HandleCharacterEraseCommand (const char* args);
    bool HandleCharacterLevelCommand (const char* args);
    bool HandleCharacterRenameCommand (const char * args);
    bool HandleCharacterReputationCommand (const char* args);
    bool HandleCharacterTitlesCommand (const char* args);

    bool HandleChannelSetOwnership (const char *args);

    bool HandlePossessCommand (const char* args);
    bool HandleUnPossessCommand (const char* args);
    bool HandleBindSightCommand (const char* args);
    bool HandleUnbindSightCommand (const char* args);

    bool HandleEventActiveListCommand (const char* args);
    bool HandleEventStartCommand (const char* args);
    bool HandleEventStopCommand (const char* args);
    bool HandleEventInfoCommand (const char* args);

    bool HandleGMCommand (const char* args);
    bool HandleGMChatCommand (const char* args);
    bool HandleGMFlyCommand (const char* args);
    bool HandleGMListFullCommand (const char* args);
    bool HandleGMListIngameCommand (const char* args);
    bool HandleGMVisibleCommand (const char* args);

    bool HandleGoCommand (const char* args);
    bool HandleGoCreatureCommand (const char* args);
    bool HandleGoGraveyardCommand (const char* args);
    bool HandleGoGridCommand (const char* args);
    bool HandleGoObjectCommand (const char* args);
    bool HandleGoTaxinodeCommand (const char* args);
    bool HandleGoTriggerCommand (const char* args);
    bool HandleGoXYCommand (const char* args);
    bool HandleGoXYZCommand (const char* args);
    bool HandleGoZoneXYCommand (const char* args);

    bool HandleGoTicketCommand (const char* args);

    bool HandleGuildCreateCommand (const char* args);
    bool HandleGuildInviteCommand (const char* args);
    bool HandleGuildUninviteCommand (const char* args);
    bool HandleGuildRankCommand (const char* args);
    bool HandleGuildDeleteCommand (const char* args);

    bool HandleInstanceListBindsCommand (const char* args);
    bool HandleInstanceUnbindCommand (const char* args);
    bool HandleInstanceStatsCommand (const char* args);
    bool HandleInstanceSaveDataCommand (const char * args);

    bool HandleLearnCommand (const char* args);
    bool HandleLearnAllCommand (const char* args);
    bool HandleLearnAllGMCommand (const char* args);
    bool HandleLearnAllCraftsCommand (const char* args);
    bool HandleLearnAllRecipesCommand (const char* args);
    bool HandleLearnAllDefaultCommand (const char* args);
    bool HandleLearnAllLangCommand (const char* args);
    bool HandleLearnAllMyClassCommand (const char* args);
    bool HandleLearnAllMyPetTalentsCommand (const char* args);
    bool HandleLearnAllMySpellsCommand (const char* args);
    bool HandleLearnAllMyTalentsCommand (const char* args);

    bool HandleListAurasCommand (const char * args);
    bool HandleListCreatureCommand (const char* args);
    bool HandleListItemCommand (const char* args);
    bool HandleListObjectCommand (const char* args);

    bool HandleLookupAreaCommand (const char* args);
    bool HandleLookupCreatureCommand (const char* args);
    bool HandleLookupEventCommand (const char* args);
    bool HandleLookupFactionCommand (const char * args);
    bool HandleLookupItemCommand (const char * args);
    bool HandleLookupItemSetCommand (const char * args);
    bool HandleLookupObjectCommand (const char* args);
    bool HandleLookupPlayerIpCommand (const char* args);
    bool HandleLookupPlayerAccountCommand (const char* args);
    bool HandleLookupPlayerEmailCommand (const char* args);
    bool HandleLookupQuestCommand (const char* args);
    bool HandleLookupSkillCommand (const char* args);
    bool HandleLookupSpellCommand (const char* args);
    bool HandleLookupTaxiNodeCommand (const char * args);
    bool HandleLookupTeleCommand (const char * args);
    bool HandleLookupMapCommand (const char* args);
    bool HandleLookupTitleCommand (const char * args);

    bool HandleOpcodeTestCommand (const char* args);

    bool HandlePDumpLoadCommand (const char *args);
    bool HandlePDumpWriteCommand (const char *args);

    bool HandleResetHonorCommand(const char * args);
    bool HandleResetConquestCommand(const char * args);
    bool HandleResetValorCommand(const char * args);
    bool HandleResetJusticeCommand(const char * args);
    bool HandleResetAchievementsCommand (const char * args);
    bool HandleResetAllCommand (const char * args);
    bool HandleResetLevelCommand (const char * args);
    bool HandleResetSpellsCommand (const char * args);
    bool HandleResetStatsCommand (const char * args);
    bool HandleResetTalentsCommand (const char * args);

    bool HandleSendItemsCommand (const char* args);
    bool HandleSendMailCommand (const char* args);
    bool HandleSendMessageCommand (const char * args);
    bool HandleSendMoneyCommand (const char* args);

    bool HandleServerCorpsesCommand (const char* args);
    bool HandleServerExitCommand (const char* args);
    bool HandleServerIdleRestartCommand (const char* args);
    bool HandleServerIdleShutDownCommand (const char* args);
    bool HandleServerInfoCommand (const char* args);
    bool HandleServerMotdCommand (const char* args);
    bool HandleServerPLimitCommand (const char* args);
    bool HandleServerRestartCommand (const char* args);
    bool HandleServerSetLogLevelCommand (const char* args);
    bool HandleServerSetMotdCommand (const char* args);
    bool HandleServerShutDownCommand (const char* args);
    bool HandleServerShutDownCancelCommand (const char* args);
    bool HandleServerSetClosedCommand (const char* args);
    bool HandleServerToggleQueryLogging (const char* args);

    bool HandleServerSetLogFileLevelCommand (const char* args);
    bool HandleServerSetDiffTimeCommand (const char* args);

    bool HandleTeleCommand (const char * args);
    bool HandleTeleAddCommand (const char * args);
    bool HandleTeleDelCommand (const char * args);
    bool HandleTeleGroupCommand (const char* args);
    bool HandleTeleNameCommand (const char* args);

    bool HandleUnBanAccountCommand (const char* args);
    bool HandleUnBanAccountByCharCommand (const char* args);
    bool HandleUnBanCharacterCommand (const char* args);
    bool HandleUnBanIPCommand (const char* args);

    bool HandleHelpCommand (const char* args);
    bool HandleCommandsCommand (const char* args);
    bool HandleStartCommand (const char* args);
    bool HandleDismountCommand (const char* args);
    bool HandleSaveCommand (const char* args);

    bool HandleSummonCommand (const char* args);
    bool HandleAppearCommand (const char* args);
    bool HandleGroupSummonCommand (const char* args);
    bool HandleRecallCommand (const char* args);
    bool HandleAnnounceCommand (const char* args);
    bool HandleNotifyCommand (const char* args);
    bool HandleGPSCommand (const char* args);
    bool HandleTaxiCheatCommand (const char* args);
    bool HandleWhispersCommand (const char* args);
    bool HandleModifyDrunkCommand (const char* args);

    bool HandleGUIDCommand (const char* args);
    bool HandleItemMoveCommand (const char* args);
    bool HandleDeMorphCommand (const char* args);
    bool HandlePInfoCommand (const char* args);
    bool HandleMuteCommand (const char* args);
    bool HandleUnmuteCommand (const char* args);
    bool HandleMovegensCommand (const char* args);
    bool HandleFreezeCommand (const char *args);
    bool HandleUnFreezeCommand (const char *args);
    bool HandleListFreezeCommand (const char* args);

    bool HandleCooldownCommand (const char* args);
    bool HandleUnLearnCommand (const char* args);
    bool HandleGetDistanceCommand (const char* args);
    bool HandleModifyStandStateCommand (const char* args);
    bool HandleDieCommand (const char* args);
    bool HandleDamageCommand (const char *args);
    bool HandleReviveCommand (const char* args);
    bool HandleModifyMorphCommand (const char* args);
    bool HandleAuraCommand (const char* args);
    bool HandleUnAuraCommand (const char* args);
    bool HandleLinkGraveCommand (const char* args);
    bool HandleNearGraveCommand (const char* args);
    bool HandleActivateObjectCommand (const char* args);
    bool HandleSpawnTransportCommand (const char* args);
    bool HandleExploreCheatCommand (const char* args);
    bool HandleHoverCommand (const char* args);
    bool HandleWaterwalkCommand (const char* args);
    bool HandleLevelUpCommand (const char* args);
    bool HandleShowAreaCommand (const char* args);
    bool HandleHideAreaCommand (const char* args);
    bool HandleAddItemCommand (const char* args);
    bool HandleAddItemSetCommand (const char* args);
    bool HandlePetTpCommand (const char* args);
    bool HandlePetUnlearnCommand (const char* args);
    bool HandlePetLearnCommand (const char* args);
    bool HandleCreatePetCommand (const char* args);

    bool HandleGroupLeaderCommand (const char* args);
    bool HandleGroupDisbandCommand (const char* args);
    bool HandleGroupRemoveCommand (const char* args);

    bool HandleBankCommand (const char* args);
    bool HandleChangeWeather (const char* args);
    bool HandleKickPlayerCommand (const char * args);

    // GM ticket command handlers
    bool HandleGMTicketListCommand (const char* args);
    bool HandleGMTicketListOnlineCommand (const char* args);
    bool HandleGMTicketListClosedCommand (const char* args);
    bool HandleGMTicketListEscalatedCommand (const char* args);
    bool HandleGMTicketGetByIdCommand (const char* args);
    bool HandleGMTicketGetByNameCommand (const char* args);
    bool HandleGMTicketCloseByIdCommand (const char* args);
    bool HandleGMTicketAssignToCommand (const char* args);
    bool HandleGMTicketUnAssignCommand (const char* args);
    bool HandleGMTicketCommentCommand (const char* args);
    bool HandleGMTicketDeleteByIdCommand (const char* args);
    bool HandleGMTicketReloadCommand (const char*);
    bool HandleToggleGMTicketSystem (const char* args);
    bool HandleGMTicketEscalateCommand (const char* args);
    bool HandleGMTicketCompleteCommand (const char* args);
    bool HandleGMTicketResponseAppendCommand (const char* args);
    bool HandleGMTicketResponseAppendLnCommand (const char* args);

    bool HandleMaxSkillCommand (const char* args);
    bool HandleSetSkillCommand (const char* args);
    bool HandleRespawnCommand (const char* args);
    bool HandleComeToMeCommand (const char *args);
    bool HandleCombatStopCommand (const char *args);

    /*bool HandleCharDeleteCommand(const char *args);
     bool HandleSendMessageCommand(const char * args);*/

    bool HandleFlushArenaPointsCommand (const char *args);
    bool HandlePlayAllCommand (const char* args);
    bool HandleRepairitemsCommand (const char* args);

    bool HandleTempGameObjectCommand (const char* args);
    bool HandleTempAddSpwCommand (const char* args);

    //! Development Commands

    /*bool HandleQuestAdd(const char * args);
     bool HandleQuestRemove(const char * args);
     bool HandleQuestComplete(const char * args);*/

    //bool HandleSet32Bit(const char* args);
    bool HandleSaveAllCommand (const char* args);

    // Utility methods for commands
    bool LookupPlayerSearchCommand (QueryResult result, int32 limit);
    bool HandleBanListHelper (QueryResult result);
    bool HandleBanHelper (BanMode mode, char const* args);
    bool HandleBanInfoHelper (uint32 accountid, char const* accountname);
    bool HandleUnBanHelper (BanMode mode, char const* args);
    void HandleCharacterLevel (Player* player, uint64 player_guid, uint32 oldlevel, uint32 newlevel);
    void HandleLearnSkillRecipesHelper (Player* player, uint32 skill_id);

    //Wintergrasp
    bool HandleWintergraspStatusCommand (const char *args);
    bool HandleWintergraspStartCommand (const char *args);
    bool HandleWintergraspStopCommand (const char *args);
    bool HandleWintergraspEnableCommand (const char *args);
    bool HandleWintergraspSwitchTeamCommand (const char *args);
    bool HandleWintergraspTimerCommand (const char *args);
    
    //Jail
    bool HandleCharacterJailCommand (const char* args);
    bool HandleCharacterUnJailCommand (const char* args);

    // Stores informations about a deleted character
    struct DeletedInfo
    {
        uint32 lowguid;          ///< the low GUID from the character
        std::string name;          ///< the character name
        uint32 accountId;          ///< the account id
        std::string accountName;          ///< the account name
        time_t deleteDate;          ///< the date at which the character has been deleted
    };

    typedef std::list<DeletedInfo> DeletedInfoList;
    bool GetDeletedCharacterInfoList (DeletedInfoList& foundList, std::string searchString = "");
    std::string GenerateDeletedCharacterGUIDsWhereStr (DeletedInfoList::const_iterator& itr, DeletedInfoList::const_iterator const& itr_end);
    void HandleCharacterDeletedListHelper (DeletedInfoList const& foundList);
    void HandleCharacterDeletedRestoreHelper (DeletedInfo const& delInfo);

private:
    WorldSession * m_session;          // != NULL for chat command call and NULL for CLI command

    // common global flag
    static bool load_command_table;
    bool sentErrorMessage;
};

class CliHandler: public ChatHandler
{
public:
    typedef void Print (void*, char const*);
    explicit CliHandler (void* callbackArg, Print* zprint) :
            m_callbackArg(callbackArg), m_print(zprint)
    {
    }

    // overwrite functions
    const char *GetArkCoreString (int32 entry) const;
    bool isAvailable (ChatCommand const& cmd) const;
    void SendSysMessage (const char *str);
    std::string GetNameLink () const;
    bool needReportToTarget (Player* chr) const;
    LocaleConstant GetSessionDbcLocale () const;
    int GetSessionDbLocaleIndex () const;

private:
    void* m_callbackArg;
    Print* m_print;
};

char const *fmtstring (char const *format, ...);

#endif
